package com.wasu.sdk_ott.http.live

import android.text.TextUtils
import android.util.Log
import com.alibaba.fastjson.JSONObject
import com.alibaba.fastjson.parser.Feature
import com.alibaba.fastjson.serializer.SerializerFeature
import com.wasu.constant.Config
import com.wasu.constant.IP_SYSTEM_APP_SECRET
import com.wasu.constant.IP_SYSTEM_AUTH_TYPE
import com.wasu.constant.LiveChannel
import com.wasu.constant.TAG
import com.wasu.sdk_ott.utils.WasuTvModelUtil
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale

/**
 * <p>------------------------------------------------------
 * <p>Copyright (C) 2020 wasu company, All rights reserved.
 * <p>------------------------------------------------------
 * <p> IP直播管理系统接口请求参数频接
 * <p>
 *
 * @author Created by zhangmz
 * @date on 2023/7/31
 */
class WasuIpLiveUtils {

    private val pattern1 = "yyyy-MM-dd"
    private val sdf1 = SimpleDateFormat(pattern1, Locale.CHINA)
    private val sdf2 = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA)

    /**
     * 生成IP直播管理系统频道请求参数
     * @param bIds 频道分组id，可传空，默认所有分组
     * @param isZip 是否压缩包数据，服务端默认0，非压缩，终端默认1，压缩
     */
    fun getQueryChannelGroupParam(
        bIds: String? = "",
        isZip: String? = "1",
        category: String? = null,
        isUseIpepg: Boolean
    ): JSONObject {
        return runCatching {
            if (isUseIpepg){
                JSONObject().apply {
                    put("command", "WASU_LIVE_CHANNEL")
                    put("region", getLiveRegion())
                }
            }else {
                val paramJson = queryCommonParam(category).apply {
                    put("bIds", bIds)
                    put("chId", "")
                    put("userId", Config.uid)
                    put("stbId", WasuTvModelUtil.wasu_bsa_getTvid())
                    put("authType", IP_SYSTEM_AUTH_TYPE)
                    // 是否ZIP压缩：0-否；1-是，默认为0
                    put("isZip", isZip)
                }
                paramJson["sign"] = generateIpLiveSign(paramJson)
                paramJson["command"] = "WASU_LIVE_CHANNEL"
                paramJson["charset"] = "UTF-8"
                paramJson
            }
        }.onFailure {
            it.printStackTrace()
        }.getOrDefault(JSONObject())
    }

    /**
     * 生成IP直播管理系统节目单类型请求参数
     * @param bIds 分组id，用来查询该分组下所有频道节目单
     * @param bId 单个频道组ID：当type为4时必填
     * @param channelId 频道ID：当type=2、5时必填，多个频道以“:”分隔；当type=1、6时可选，多个频道以“:”分隔
     * @param type 节目单类型：
                        1：取所有或若干个频道的当天节目单
                        2：取若干个频道的所有节目单
                        3：取所有频道的当前时间节目单
                        4：取频道分组下所有频道的当前时间节目单
                        5：取若干个频道的当前时间节目单
                        6：取所有或若干个频道的若干天节目单
     * @param getType 获取节目单类型：1-直播；2-回放，默认为1
     * @param beginDate 开始日期：当type=6时可选(默认为今天)，格式为“yyyy-MM-dd”
     * @param endDate 结束日期：当type=6时可选(默认为今天)，格式为“yyyy-MM-dd”
     */
    fun getQueryProgramListParam(
        type: String,
        getType: String? = "",
        bIds: String? = "",
        bId: String? = "",
        channelId: String? = "",
        beginDate: String? = "",
        endDate: String? = "",
        isZip: String? = "1",
        category: String? = null,
        isUseIpepg: Boolean
    ): JSONObject {
        return runCatching {
            if (isUseIpepg){
                JSONObject().apply {
                    put("command", "WASU_LIVE_EVENT")
                    put("region", getLiveRegion())
                    put("type", type)
                    put("chId", channelId)
                }
            }else {
                val paramJson = queryCommonParam(category).apply {
                    put("type", type)
                    if (getType?.isNotEmpty() == true){ put("getType", getType) }
                    if (type == "2" || type == "5"){
                        if (channelId.isNullOrEmpty()){
                            Throwable("type = $type, channel id can not be null")
                            return@apply
                        }
                        put("chId", channelId)
                    }else if (type == "1" || type == "6"){
                        if (channelId?.isNotEmpty() == true){
                            put("chId", channelId)
                        }
                    }
                    if (type == "4"){
                        if (bId.isNullOrEmpty()){
                            Throwable("type = $type, bIds id can not be null")
                            return@apply
                        }
                        put("bId", bId)
                    }
                    if (bIds?.isNotEmpty() == true){ put("bIds", bIds) }
                    if (type == "1"){
                        put("date", sdf1.format(Calendar.getInstance().time))
                    }
                    if (type == "3" || type == "4" || type == "5"){
                        put("date", sdf2.format(Calendar.getInstance().time))
                    }
                    if (beginDate?.isNotEmpty() == true){
                        put("beginDate", sdf1.format(if (beginDate.length > pattern1.length) sdf2.parse(beginDate)!! else sdf1.parse(beginDate)))
                    }
                    if (endDate?.isNotEmpty() == true){
                        put("endDate", sdf1.format(if (endDate.length > pattern1.length) sdf2.parse(endDate)!! else sdf1.parse(endDate)))
                    }
                    // 是否ZIP压缩：0-否；1-是，默认为0
                    put("isZip", isZip)
                    // 1:倒序排序(当前日期最前，如3、5、4、2、1)
                    // 2:升序排序(当前日期最前，如3、4、5、1、2)
                    // 服务端默认1，终端默认传2
                    put("sortType", "2")
                }
                paramJson["sign"] = generateIpLiveSign(paramJson)
                paramJson["command"] = "WASU_LIVE_EVENT"
                paramJson["charset"] = "UTF-8"
                paramJson
            }
        }.onFailure {
            it.printStackTrace()
        }.getOrDefault(JSONObject())
    }

    /**
     * 查询单个频道信息
     * chId 和 chName 有且只能有一个不为空
     */
    fun getQueryChannelParam(
        chId: String? = "",
        chName: String? = "",
        category: String? = null
    ): JSONObject {
        if (chId.isNullOrEmpty() && chName.isNullOrEmpty()){
            Log.e(TAG, "query channel info, channel id and name can not all be null")
            return JSONObject()
        }
        return runCatching {
            val paramJson = queryCommonParam(category).apply {
                // 频道ID或频道名称必输其一，且只能输一个
                if (chId?.isNotEmpty() == true && chName?.isNotEmpty() == true){
                    put("chId", chId)
                    put("chName", "")
                }else if (chId?.isNotEmpty() == true){
                    put("chId", chId)
                    put("chName", "")
                }else if (chName?.isNotEmpty() == true){
                    put("chId", "")
                    put("chName", chName)
                }else {
                    put("chId", "")
                    put("chName", "")
                }
                put("fields", "")
            }
            paramJson["sign"] = generateIpLiveSign(paramJson)
            paramJson["command"] = "WASU_LIVE_CHANNEL_DTL"
            paramJson["charset"] = "UTF-8"
            paramJson
        }.onFailure {
            it.printStackTrace()
        }.getOrDefault(JSONObject())
    }

    /**
     * DVB 模式下查询频道授权列表
     */
    fun getQueryChannelAuthParam(): JSONObject {
        return runCatching {
            JSONObject().apply {
                put("command", "WASU_LIVE_PURCHASED")
                put("region", getLiveRegion())
                put("stbId", WasuTvModelUtil.wasu_bsa_getTvid())
            }
        }.onFailure {
            it.printStackTrace()
        }.getOrDefault(JSONObject())
    }

    /**
     * 查询IP直播管理系统分组频道节目单等版本信息
     * @param type 请求类型：
                    0：取所有版本号
                    1：频道分组信息版本号
                    2：节目单版本号（所有频道当天节目单）
                    3：节目单版本号（单个频道所有节目单）
     * @param chId 频道ID：当type=0、3时填写，如果为空则获取所有频道数据
     */
    fun getQueryVersionParam(
        type: String? = "0",
        chId: String? = "",
        category: String? = null,
        isUseIpepg: Boolean
    ): JSONObject {
        return runCatching {
            if (isUseIpepg){
                JSONObject().apply {
                    put("command", "WASU_LIVE_VERSION")
                    put("region", getLiveRegion())
                    put("type", type)
                }
            }else {
                val paramJson = queryCommonParam(category).apply {
                    put("type", type)
                    put("chId", chId)
                }
                paramJson["sign"] = generateIpLiveSign(paramJson)
                paramJson["command"] = "WASU_LIVE_VERSION"
                paramJson["charset"] = "UTF-8"
                paramJson
            }
        }.onFailure {
            it.printStackTrace()
        }.getOrDefault(JSONObject())
    }

    /**
     * IP直播管理系统的几个公共请求 6 个参数
     */
    private fun queryCommonParam(category: String? = null) = JSONObject().apply {
        LiveChannel.queryCommonParam(category, this)
    }

    /**
     * 生成签名
     */
    private fun generateIpLiveSign(json: JSONObject): String {
        return runCatching {
            Log.v(TAG, "start generate sign params:$json")

            val iterator: MutableIterator<MutableMap.MutableEntry<String, Any>> = json.entries.iterator()
            while (iterator.hasNext()){
                val map: Map.Entry<String, Any> = iterator.next()
                if (TextUtils.isEmpty(map.value as? String)){
                    iterator.remove()
                }
            }
            // json按照key做排序，从小到大
            val sortMessage = JSONObject.toJSONString(json, SerializerFeature.MapSortField)
            Log.v(TAG, "remove and sort generate sign sortMessage:$sortMessage")
            val signStr = conversionJsonToStr(JSONObject.parseObject(sortMessage, Feature.OrderedField)) + IP_SYSTEM_APP_SECRET
            Log.v(TAG, "finally generate sign signStr:$signStr")
            WasuTvModelUtil.md5(signStr.toByteArray()).toUpperCase(Locale.getDefault())
        }.getOrDefault("")
    }

    /**
     * 将json转成以&分隔的key=value字符串
     */
    private fun conversionJsonToStr(jsonStr: JSONObject): String {
        val sb = StringBuffer()
        jsonStr.mapKeys {
            sb.append(it.key).append("=").append(it.value).append("&")
        }
        val result = sb.toString()
        return result.substring(0, result.length - 1)
    }

}